www.gusucode.com > VC 2D游戏编辑器-源码程序 > VC 2D游戏编辑器-源码程序/code/game_Source/GameLib/findpath.cpp
//Download by http://www.NewXing.com #include "findpath.h" #include "define.h" #include "globle.h" #include "globle_func.h" #include "..\\newgame.h" FINDPATH8::FINDPATH8( ) { Dir = NULL; Dir1 = NULL; bBeginDir = false; IsFind = false; IsTooFar = false; Table = new bool[TABLE_X*TABLE_Y]; MaxAct=8; //移动方向总数 Level=-1; //第几步 LevelComplete=0; //这一步的搜索是否完成 AllComplete=0; //全部搜索是否完成 cur_x=1; cur_y=1; //现在的x和y坐标 TargetX=0; TargetY=0; //目标x和y坐标 BaseX=0; BaseY=0; //开始x和y坐标 } FINDPATH8::~FINDPATH8( ) { PA_SAFE_DELETE(Table); } void FINDPATH8::find(long lStartX, long lStartY, long lEndX, long lEndY) { if(Dir) { while(Dir) { pLink1 = Dir; Dir = Dir->Next; delete [] pLink1; } Dir = NULL; } cur_x = BaseX = lStartX/32; cur_y = BaseY = lStartY/32; TargetX = iTX = lEndX/32; TargetY = iTY = lEndY/32; if((TargetX == cur_x)&&(TargetY == cur_y)) { IsFind = true; return; } int nx, ny; do { nx = abs(iTX - BaseX); ny = abs(iTY - BaseY); if(nx > 32) if(iTY > BaseX) TargetX = BaseX + 32; else TargetX = BaseX - 32; if(ny > 32) if(iTY > BaseY) TargetY = BaseY + 32; else TargetY = BaseY - 32; FindWay( ); if(!IsFind) { FindNear( ); if(Dir1) { while(Dir1) { pLink1 = Dir1; Dir1 = Dir1->Next; delete [] pLink1; } Dir1 = NULL; } cur_x = BaseX; cur_y = BaseY; FindWay( ); } if(Dir == NULL) { Dir = Dir1; Dir1 = NULL; } else { pLink1->Next = Dir1; Dir1 = NULL; } BaseX = TargetX; BaseY = TargetY; }while((nx > 32)||(ny > 32)); iTX = TargetX; iTY = TargetY; pLink1 = NULL; } void FINDPATH8::FindWay( ) { Level=-1; //第几步 LevelComplete=0; //这一步的搜索是否完成 AllComplete=0; //全部搜索是否完成 IsFind = false; IsTooFar = false; if((BaseX == TargetX)&&(BaseY == TargetY)) { IsFind = true; return; } iTableStartX = (BaseX+TargetX-TABLE_X)>>1; iTableStartY = (BaseY+TargetY-TABLE_Y)>>1; _pDir* pLink; memset(Table,0,TABLE_X*TABLE_Y*sizeof(bool)); Table[(cur_y-iTableStartY)*TABLE_X+cur_x-iTableStartX]=true; //做已到过标记 while (!AllComplete) //是否全部搜索完 { Level++;LevelComplete=0; //搜索下一步 if(Level > 1000)//搜索步数过多 { LevelComplete=AllComplete=1; //退出 IsTooFar = true; } pLink = new _pDir; pLink->dir = 0; pLink->Next = NULL; if(Dir1 == NULL) { pLink->Back = NULL; Dir1 = pLink; pLink1 = pLink; pLink = NULL; } else { pLink->Back = pLink1; pLink1->Next = pLink; pLink1 = pLink; pLink = NULL; } while (!LevelComplete) { pLink1->dir=GetNextAct( ); //改变移动方向 if (pLink1->dir>MaxAct) { Back( ); if (Level<0) //全部搜索完仍无结果 LevelComplete=AllComplete=1; //退出 } else if (ActOK( )) //移动方向是否合理 { Test( ); //测试是否已到目标 LevelComplete=1; //该步搜索完成 } } } } void FINDPATH8::Test( ) { if ((cur_x==TargetX)&&(cur_y==TargetY)) //已到目标 { IsFind = true; LevelComplete=AllComplete=1; //完成搜索 } } int FINDPATH8::ActOK( ) { int tx=cur_x+dir8_x[pLink1->dir-1]; //将到点的x坐标 int ty=cur_y+dir8_y[pLink1->dir-1]; //将到点的y坐标 if (pLink1->dir>MaxAct) //方向错误? return 0; if ((tx>=Map->pHeader.nWidth)||(tx<0)||(tx < iTableStartX)||(tx >= iTableStartX+TABLE_X)) //x坐标出界? return 0; if ((ty>=Map->pHeader.nHeight)||(ty<0)||(ty < iTableStartY)||(ty >= iTableStartY+TABLE_Y)) //y坐标出界? return 0; if (Table[(ty-iTableStartY)*TABLE_X+tx-iTableStartX]) //已到过? return 0; if (Map->pSurfaceData[ty*Map->pHeader.nWidth+tx].nPass == 0) //有障碍? return 0; cur_x=tx; cur_y=ty; //移动 Table[(ty-iTableStartY)*TABLE_X+tx-iTableStartX]=true; //做已到过标记 return 1; } void FINDPATH8::Back( ) { Level--; //回上一层 if(Level < 0) { delete Dir1; Dir1 = NULL; return; } cur_x -=dir8_x[pLink1->Back->dir-1]; cur_y -=dir8_y[pLink1->Back->dir-1]; //退回原来的点 pLink1 = pLink1->Back; delete[] pLink1->Next; //清除方向 pLink1->Next = NULL; } int FINDPATH8::GetNextAct( ) //找到下一个移动方向。 //仔细看! { float dis[8]; int order[8]; float t=2000; int i, j; if(Level > 0) { for (i = 0; i < 8; i++) { dis[i]=(dSqrt[dSquare[abs(cur_x+dir8_x[i]-TargetX)]+dSquare[abs(cur_y+dir8_y[i]-TargetY)]])*2+abs(dir8_y[i]-dir8_y[pLink1->Back->dir-1])+abs(dir8_x[i]-dir8_x[pLink1->Back->dir-1])+(abs(dir8_y[i]-dir8_y[pLink1->Back->dir-1])/2+abs(dir8_x[i]-dir8_x[pLink1->Back->dir-1])/2)*2; } } else { for (i = 0; i < 8; i++) { dis[i]=dSqrt[dSquare[abs(cur_x+dir8_x[i]-TargetX)]+dSquare[abs(cur_y+dir8_y[i]-TargetY)]]; } } for (i = 0;i<8;i++) if (dis[i]<t) { order[0]=i+1; t=dis[i]; } if (pLink1->dir==0) return order[0]; dis[order[0]-1] = 32767; for(i = 1; i < 8; i++) { t = 32767; for(j = 0; j < 8; j++) { if(dis[j] < t) { order[i] = j + 1; t = dis[j]; } } dis[order[i]-1] = 32767; } if (pLink1->dir==order[0]) return order[1]; if (pLink1->dir==order[1]) return order[2]; if (pLink1->dir==order[2]) return order[3]; if (pLink1->dir==order[3]) return order[4]; if (pLink1->dir==order[4]) return order[5]; if (pLink1->dir==order[5]) return order[6]; if (pLink1->dir==order[6]) return order[7]; if (pLink1->dir==order[7]) return 9; return 9; } void FINDPATH8::FindNear( ) { long lStartX, lStartY, lNearX, lNearY, lR; int i; lStartX = TargetX; lStartY = TargetY; lR = 0; bool IsFindNear = false; while(!IsFindNear) { lR ++; for(i = 0; i < 360; i +=1) { lNearX = (long)(lR*cos_O[i]) + lStartX; lNearY = (long)(lR*sin_O[i]) + lStartY; if(lNearX < 0) lNearX = 0; if(lNearY < 0) lNearY = 0; if(lNearX > Map->pHeader.nWidth-1) lNearX = Map->pHeader.nWidth-1; if(lNearY > Map->pHeader.nHeight-1) lNearY = Map->pHeader.nHeight-1; if(Table[(lNearY-iTableStartY)*TABLE_X+lNearX-iTableStartX]) { IsFindNear = true; break; } } } TargetX = lNearX; TargetY = lNearY; } /*****************************************************************************/ FINDPATH4::FINDPATH4( ) { Dir = NULL; Dir1 = NULL; bBeginDir = false; IsFind = false; IsTooFar = false; Table = new bool[TABLE_X*TABLE_Y]; MaxAct=4; //移动方向总数 Level=-1; //第几步 LevelComplete=0; //这一步的搜索是否完成 AllComplete=0; //全部搜索是否完成 cur_x=1; cur_y=1; //现在的x和y坐标 TargetX=0; TargetY=0; //目标x和y坐标 BaseX=0; BaseY=0; //开始x和y坐标 } FINDPATH4::~FINDPATH4( ) { PA_SAFE_DELETE(Table); } void FINDPATH4::find(long lStartX, long lStartY, long lEndX, long lEndY) { if(Dir) { while(Dir) { pLink1 = Dir; Dir = Dir->Next; delete [] pLink1; } Dir = NULL; } cur_x = BaseX = lStartX/32; cur_y = BaseY = lStartY/32; TargetX = iTX = lEndX/32; TargetY = iTY = lEndY/32; if((TargetX == cur_x)&&(TargetY == cur_y)) { IsFind = true; return; } int nx, ny; do { nx = abs(iTX - BaseX); ny = abs(iTY - BaseY); if(nx > 32) if(iTY > BaseX) TargetX = BaseX + 32; else TargetX = BaseX - 32; if(ny > 32) if(iTY > BaseY) TargetY = BaseY + 32; else TargetY = BaseY - 32; FindWay( ); if(!IsFind) { FindNear( ); if(Dir1) { while(Dir1) { pLink1 = Dir1; Dir1 = Dir1->Next; delete [] pLink1; } Dir1 = NULL; } cur_x = BaseX; cur_y = BaseY; FindWay( ); } if(Dir == NULL) { Dir = Dir1; Dir1 = NULL; } else { pLink1->Next = Dir1; Dir1 = NULL; } BaseX = TargetX; BaseY = TargetY; }while((nx > 32)||(ny > 32)); iTX = TargetX; iTY = TargetY; pLink1 = NULL; } void FINDPATH4::FindWay( ) { Level=-1; //第几步 LevelComplete=0; //这一步的搜索是否完成 AllComplete=0; //全部搜索是否完成 IsFind = false; IsTooFar = false; if((BaseX == TargetX)&&(BaseY == TargetY)) { IsFind = true; return; } iTableStartX = (BaseX+TargetX-TABLE_X)>>1; iTableStartY = (BaseY+TargetY-TABLE_Y)>>1; _pDir* pLink; memset(Table,0,TABLE_X*TABLE_Y*sizeof(bool)); Table[(cur_y-iTableStartY)*TABLE_X+cur_x-iTableStartX]=true; //做已到过标记 while (!AllComplete) //是否全部搜索完 { Level++;LevelComplete=0; //搜索下一步 if(Level > 1000)//搜索步数过多 { LevelComplete=AllComplete=1; //退出 IsTooFar = true; } pLink = new _pDir; pLink->dir = 0; pLink->Next = NULL; if(Dir1 == NULL) { pLink->Back = NULL; Dir1 = pLink; pLink1 = pLink; pLink = NULL; } else { pLink->Back = pLink1; pLink1->Next = pLink; pLink1 = pLink; pLink = NULL; } while (!LevelComplete) { pLink1->dir=GetNextAct( ); //改变移动方向 if (pLink1->dir>MaxAct) { Back( ); if (Level<0) //全部搜索完仍无结果 LevelComplete=AllComplete=1; //退出 } else if (ActOK( )) //移动方向是否合理 { Test( ); //测试是否已到目标 LevelComplete=1; //该步搜索完成 } } } } void FINDPATH4::Test( ) { if ((cur_x==TargetX)&&(cur_y==TargetY)) //已到目标 { IsFind = true; LevelComplete=AllComplete=1; //完成搜索 } } int FINDPATH4::ActOK( ) { int tx=cur_x+dir4_x[pLink1->dir-1]; //将到点的x坐标 int ty=cur_y+dir4_y[pLink1->dir-1]; //将到点的y坐标 if (pLink1->dir>MaxAct) //方向错误? return 0; if ((tx>=Map->pHeader.nWidth)||(tx<0)||(tx < iTableStartX)||(tx >= iTableStartX+TABLE_X)) //x坐标出界? return 0; if ((ty>=Map->pHeader.nHeight)||(ty<0)||(ty < iTableStartY)||(ty >= iTableStartY+TABLE_Y)) //y坐标出界? return 0; if (Table[(ty-iTableStartY)*TABLE_X+tx-iTableStartX]) //已到过? return 0; if (Map->pSurfaceData[ty*Map->pHeader.nWidth+tx].nPass == 0) //有障碍? return 0; cur_x=tx; cur_y=ty; //移动 Table[(ty-iTableStartY)*TABLE_X+tx-iTableStartX]=true; //做已到过标记 return 1; } void FINDPATH4::Back( ) { Level--; //回上一层 if(Level < 0) { delete Dir1; Dir1 = NULL; return; } cur_x -=dir4_x[pLink1->Back->dir-1]; cur_y -=dir4_y[pLink1->Back->dir-1]; //退回原来的点 pLink1 = pLink1->Back; delete[] pLink1->Next; //清除方向 pLink1->Next = NULL; } int FINDPATH4::GetNextAct( ) //找到下一个移动方向。 //仔细看! { int dis[4]; int order[4]; int t=2000; int i, j; if(Level > 0) { for (i = 0; i < 4; i++) { dis[i]=abs(cur_x+dir4_x[i]-TargetX) + abs(cur_y+dir4_y[i]-TargetY); } } else { for (i = 0; i < 4; i++) { dis[i]=abs(cur_x+dir4_x[i]-TargetX) + abs(cur_y+dir4_y[i]-TargetY); //dis[i]=dSqrt[dSquare[abs(cur_x+dir4_x[i]-TargetX)]+dSquare[abs(cur_y+dir4_y[i]-TargetY)]]; } } for (i = 0;i<4;i++) if (dis[i]<t) { order[0]=i+1; t=dis[i]; } if (pLink1->dir==0) return order[0]; dis[order[0]-1] = 32767; for(i = 1; i < 4; i++) { t = 32767; for(j = 0; j < 4; j++) { if(dis[j] < t) { order[i] = j + 1; t = dis[j]; } } dis[order[i]-1] = 32767; } if (pLink1->dir==order[0]) return order[1]; if (pLink1->dir==order[1]) return order[2]; if (pLink1->dir==order[2]) return order[3]; if (pLink1->dir==order[3]) return 5; return 5; } void FINDPATH4::FindNear( ) { long lStartX, lStartY, lNearX, lNearY, lR; int i; lStartX = TargetX; lStartY = TargetY; lR = 0; bool IsFindNear = false; while(!IsFindNear) { lR ++; for(i = 0; i < 360; i +=1) { lNearX = (long)(lR*cos_O[i]) + lStartX; lNearY = (long)(lR*sin_O[i]) + lStartY; if(lNearX < 0) lNearX = 0; if(lNearY < 0) lNearY = 0; if(lNearX > Map->pHeader.nWidth-1) lNearX = Map->pHeader.nWidth-1; if(lNearY > Map->pHeader.nHeight-1) lNearY = Map->pHeader.nHeight-1; if(Table[(lNearY-iTableStartY)*TABLE_X+lNearX-iTableStartX]) { IsFindNear = true; break; } } } TargetX = lNearX; TargetY = lNearY; }